#ifndef SD_PTSUBSCRIBER_HH_
#define SD_PTSUBSCRIBER_HH_

#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>

#include "SDPltDataReaderListener.hpp"

using namespace eprosima::fastdds::dds;

template <class TS_T, class DT_T>
class SDPltSubscriber{
private:
    DomainParticipant* participant_;
    Subscriber* sub_;
    TypeSupport typeSupport_;
    Topic* topic_;
    SDPltDataReaderListener<DT_T>* listener_;
    DataReader* reader_;
    std::string topicname_;
    std::string dataname_;
    bool ok_;


public:

    SDPltSubscriber(std::string topicname, std::string dataname, void(*cbf)(DT_T*),ReliabilityQosPolicyKind reliability_):typeSupport_(new TS_T()){
        if(topicname.length()<1&&cbf==nullptr){
            this->ok_=false;
            return;
        }
        this->participant_=nullptr;
        this->sub_=nullptr;
        this->topic_ = nullptr;
        this->reader_=nullptr;       
        this->topicname_=topicname;
        this->dataname_=dataname;
        this->listener_=new SDPltDataReaderListener<DT_T>(cbf);
        this->ok_= init(reliability_);
    }
    ~SDPltSubscriber(){
        release();
    }

private:
    void release(){
        if(!this->ok_)return;
        if(this->topic_!=nullptr){
            this->participant_->delete_topic(this->topic_); 
            this->topic_=nullptr;
        }

        if(this->reader_!=nullptr){
            this->sub_->delete_datareader(this->reader_);
            this->reader_=nullptr;
        }

        if(this->sub_!=nullptr){
            this->participant_->delete_subscriber(this->sub_);
            this->sub_=nullptr;   
        }
        if(this->participant_!=nullptr){
            DomainParticipantFactory::get_instance()->delete_participant(this->participant_); 
            this->participant_=nullptr;
        }
    }
    bool init(ReliabilityQosPolicyKind reliability_) {
        DomainParticipantQos participantQos;
        participantQos.name("SD_BASE_SEQ_MESSAGE_QOS_SUB");
        this->participant_ = DomainParticipantFactory::get_instance()->create_participant(0, participantQos);
        if (this->participant_ == nullptr) {
            std::cout << "Domain Participant creating error!" << std::endl;
            return false;
        }
    
        this->typeSupport_.register_type(this->participant_);
    
        this->topic_ = this->participant_->create_topic(this->topicname_, this->dataname_, TOPIC_QOS_DEFAULT);
        if (this->topic_ == nullptr) {
            std::cout << "Topic creating error!" << std::endl;
            return false;
        }
    
        SubscriberQos subscriberqos_ = SUBSCRIBER_QOS_DEFAULT;
        this->sub_ = this->participant_->create_subscriber(subscriberqos_, nullptr);
        if (this->sub_ == nullptr) {
            std::cout << "Subscriber creating error!" << std::endl;
            return false;
        }
    
        DataReaderQos readerqos_ = DATAREADER_QOS_DEFAULT;
        ReliabilityQosPolicy reliabilityqospolicy_;
        reliabilityqospolicy_.kind = reliability_;
        readerqos_.reliability(reliabilityqospolicy_);
    
        // 设置历史深度和资源限制
        readerqos_.history().kind = KEEP_LAST_HISTORY_QOS;
        readerqos_.history().depth = 10; // 根据需要设置历史深度
        readerqos_.resource_limits().max_samples = 100;
        readerqos_.resource_limits().max_instances = 10;
        readerqos_.resource_limits().max_samples_per_instance = 10;
    
        this->reader_ = this->sub_->create_datareader(this->topic_, readerqos_, this->listener_);
    
        if (this->reader_ == nullptr) {
            std::cout << "DataReader creating error!" << std::endl;
            return false;
        }
    
        return true;
    }
};

#endif